package game.source.manager;

import game.source.gui.GamePanel;
import game.source.gui.GuiBackground;
import game.source.gui.GuiComponent;
import game.source.gui.hud.Hud;
import game.source.gui.price.GuiPriceLevelUp;
import game.source.gui.price.GuiPriceNewLife;
import game.source.gui.ship.GuiEnemyBoss;
import game.source.gui.ship.GuiEnemyShipOne;
import game.source.gui.ship.GuiEnemyShipThree;
import game.source.gui.ship.GuiEnemyShipTwo;
import game.source.gui.ship.GuiPlayerShip;
import game.source.gui.shot.GuiShotBasic;
import game.source.gui.shot.GuiShotMax;
import game.source.gui.shot.GuiShotMedium;
import game.source.physics.Physics;
import game.source.price.Price;
import game.source.price.PriceLevelUp;
import game.source.price.PriceNewLife;
import game.source.ships.EnemyBoss;
import game.source.ships.EnemyShip;
import game.source.ships.EnemyShipOne;
import game.source.ships.EnemyShipThree;
import game.source.ships.EnemyShipTwo;
import game.source.ships.GameInterface;
import game.source.ships.PlayerShip;
import game.source.ships.Ship;
import game.source.shot.GuiShotInterface.Level;
import game.source.shot.GuiShotInterface.Shooter;
import game.source.shot.Shot;
import game.source.shot.ShotBasic;
import game.source.shot.ShotMax;
import game.source.shot.ShotMedium;
import game.source.util.InputControl;
import game.source.util.TimerControlInterface;
import game.source.util.TrackerPlayer;

import java.awt.Point;
import java.util.Vector;


/*GameManager:
 * Faz o gerenciamento do jogo, isto é, armazena os elementos que estão na tela,
 * permite a criação de elementos e os exibe na ordem correta.
 * */
public class GameManager extends GuiComponent implements GameInterface,TimerControlInterface{
	private		GuiBackground 			backgraound;		//Fundo de tela
	private		Vector<EnemyShip>		enemyShips;			//Os enimigos na tela
	private		Vector<Shot>			playerShots;		//Os tiros do player
	private		Vector<Shot>			enemyShots;			//Os tiros dos inimigos
	private		Vector<Price>			prices;				//Prêmios para o jogador
	private 	PlayerShip				player;				//O player (engine)
	private		Hud						hud;
	private 	TrackerPlayer			tracker;			//Tracker para a posição player
	private 	GamePanel				panel;				//Painel do jogo

	public GameManager(String bg_path, GamePanel painel){
		this.panel			= painel;
		this.backgraound	= new GuiBackground(bg_path, 150);
		this.enemyShips		= new Vector<EnemyShip>();
		this.playerShots	= new Vector<Shot>();
		this.enemyShots		= new Vector<Shot>();
		this.prices			= new Vector<Price>();
		this.tracker		= new TrackerPlayer();		
		this.player			= new PlayerShip(new Point(this.getPanelWidth()/2,this.getPanelHeight()/2),new GuiPlayerShip(),this,this.tracker);
		this.hud			= new Hud(this.panel,this.player);
		new InputControl(this.panel,this.player);
	}

	@Override
	public void show(long time){
		//Exibe o fundo:
		backgraound.show(time);
		//Verifica se os inimigos estão na tela:
		for(int indexEnemy = 0; indexEnemy < this.enemyShips.size();indexEnemy++){
			if(this.enemyShips.get(indexEnemy).getY0() > this.getPanelHeight()){
				this.enemyShips.get(indexEnemy).end();
				this.tracker.remove(this.enemyShips.get(indexEnemy));
				this.enemyShips.remove(indexEnemy);	
				indexEnemy--;
			}
		}	
		//Verifica se os tiros estão na tela:

		for(int indexShot = 0; indexShot < this.playerShots.size(); indexShot++){
			if(this.playerShots.get(indexShot).getY0()+this.playerShots.get(indexShot).getHeight() < 0){
				this.playerShots.get(indexShot).end();
				this.playerShots.remove(indexShot);
				indexShot--;
			}
		}	



		for(int indexShot = 0; indexShot < this.enemyShots.size(); indexShot++){
			if(this.enemyShots.get(indexShot).getY0() > this.getPanelHeight()){
				this.enemyShots.get(indexShot).end();
				this.enemyShots.remove(indexShot);
				indexShot--;
			}
		}	

		//Verifica se os prêmios estão na tela:

		for(int indexPrice = 0; indexPrice < this.prices.size(); indexPrice++){
			if(this.prices.get(indexPrice).getY0() > this.getPanelHeight()){
				this.prices.remove(indexPrice);
				indexPrice--;
			}
		}	


		//Verifica testa a colisão dos tiros com os inimigos

		for(int indexShip = 0; indexShip < this.enemyShips.size(); indexShip++){
			for(int indexShot = 0; indexShot < this.playerShots.size(); indexShot++){
				if(Physics.colide(this.playerShots.get(indexShot), 
						this.enemyShips.get(indexShip))){ 
					this.playerShots.get(indexShot).action(this.enemyShips.get(indexShip));
					this.enemyShips.get(indexShip).reciveFire(Level.BASIC);
				}
			}
		}	


		//Verifica a colisão dos tiros com o player
		for(int indexShot = 0; indexShot < this.enemyShots.size(); indexShot++){
			if(Physics.colide(this.enemyShots.get(indexShot),this.player)){
				this.enemyShots.get(indexShot).action(this.player);
				this.player.reciveFire(Level.BASIC);
				break;
			}
		}	

		//Verifica se os prêmios colidem com o player
		for(int indexPrice = 0; indexPrice < this.prices.size(); indexPrice++){
			if(Physics.colide(this.player,this.prices.get(indexPrice))){
				this.prices.get(indexPrice).action();
				this.prices.remove(indexPrice);
				indexPrice--;
			}
		}	

		//Exibe os tiros:
		for(int i = 0; i < this.playerShots.size();i++){
			if(this.playerShots.get(i) != null){
				this.playerShots.get(i).show(time);
			}
		}	

		for(int i = 0; i < this.enemyShots.size();i++){
			if(this.enemyShots.get(i) != null){
				this.enemyShots.get(i).show(time);
			}
		}	
		//Exibe os inimigos:
		for(int i = 0; i < this.enemyShips.size();i++){
			if(this.enemyShips.get(i) != null){
				this.enemyShips.get(i).show(time);
			}
		}	

		//Exibe os prêmios:
		for(int i = 0; i < this.prices.size();i++){
			if(this.prices.get(i) != null){
				this.prices.get(i).show(time);
			}
		}	

		//Exibe o player:
		this.player.show(time);	

		//Exibe o hud:
		this.hud.show(time);
	}

	@Override
	public void createEnemy(Point start,EnemyType type){//Cria inimigos, passando o ponto inicial
		EnemyShip tmp;
		switch (type) {
		case ENEMY_01:
			tmp = new EnemyShipOne(start,new GuiEnemyShipOne(),this);
			break;
		case ENEMY_02:
			tmp = new EnemyShipTwo(start,new GuiEnemyShipTwo(),this);
			break;
		case ENEMY_03:
			tmp = new EnemyShipThree(start,new GuiEnemyShipThree(),this);
			break;
		case BOSS:
			tmp = new EnemyBoss(start,new GuiEnemyBoss(),this);
			break;
		default:
			tmp = new EnemyShipOne(start,new GuiEnemyShipOne(),this);
			break;
		}
		this.enemyShips.add(tmp);
		this.tracker.add(tmp);	
	}

	@Override
	public void createPrice(Point start,PriceType type){//Cria os prêmios, passando o ponto que ele inicia e o seu tipo
		switch (type) {
		case LevelUp:
			this.prices.add(new PriceLevelUp(new GuiPriceLevelUp(),start,this.player));
			break;
		case NewLife:
			this.prices.add(new PriceNewLife(new GuiPriceNewLife(),start,this.player));
			break;
		}
	}

	@Override
	public void createShot(Ship ship, Shooter shooter, Level level){//Cria os tiros, passando quem atirou, se esse é o player ou um inimigo e o nível do tiro
		Point tmp = new Point(ship.getGui().getX0()+ship.getGui().getWidth()/2,ship.getGui().getY0());
		switch (level) {
		case MAX:
			if(shooter == Shooter.PLAYER){
				this.playerShots.add(new ShotMax(new GuiShotMax(), Shooter.PLAYER, this, tmp));
			}else{
				this.enemyShots.add(new ShotMax(new GuiShotMax(), Shooter.ENEMY, this, tmp));
			}
			break;
		case MEDIUM:
			if(shooter == Shooter.PLAYER){
				this.playerShots.add(new ShotMedium(new GuiShotMedium(), Shooter.PLAYER, this, tmp));
			}else{
				this.enemyShots.add(new ShotMedium(new GuiShotMedium(), Shooter.ENEMY, this, tmp));
			}
			break;
		case BASIC:
			if(shooter == Shooter.PLAYER){
				this.playerShots.add(new ShotBasic(new GuiShotBasic(), Shooter.PLAYER, this, tmp));
			}else{
				this.enemyShots.add(new ShotBasic(new GuiShotBasic(), Shooter.ENEMY, this, tmp));
			}
			break;
		}	
	}

	@Override
	public void removeEnemy(EnemyShip enemy){//remove o inimigo passado no argumento
		enemy.end();
		this.enemyShips.remove(enemy);		
		this.tracker.remove(enemy);	
	}

	@Override
	public void removeShot(Shot shot){//remove o tiro passado no argumento
		shot.end();
		this.playerShots.remove(shot);	
		this.enemyShots.remove(shot);	
	}
	@Override
	public void removePrice(Price price){//remove o prêmio passado no argumento
		this.prices.remove(price);	
	}

	@Override
	public void gameOver(){//Faz o game over		
		this.hud.gameOver();		
	}
	@Override
	public void gameWin() {
		this.hud.gameWin();
	}

	@Override
	public int getGameWidth() {
		return this.getPanelWidth();
	}

	@Override
	public int getGameHeight() {
		return this.getPanelHeight();
	}
	@Override
	public void start() {
		for(Ship s: this.enemyShips){
			s.start();
		}
		this.player.start();		
	}
	@Override
	public void play() {
		for(Ship s: this.enemyShips){
			s.play();
		}
		this.player.play();
	}

	@Override
	public void pause() {
		for(Ship s: this.enemyShips){
			s.pause();
		}
		this.player.pause();
	}

	@Override
	public void end() {
		for(Ship s: this.enemyShips){
			s.end();
		}
		this.player.end();
	}
	@Override
	public boolean isPaused() {
		return this.player.isPaused();
	}
}
